--[[
    author:Lee
    time:2021-10-18 11:59:04
]]
local require = require
local loadstring = loadstring
local ngx = ngx
local type = type
local tostring = tostring
local table = table
local tonumber = tonumber
local assert = assert

local setmetatable = setmetatable

local uu = require("modules.commhm.utils")
local log = require("modules.commhm.log")

local ns_rsa = require("modules.commhm.resty.rsa")
local ns_resty_str = require("resty.string")
local cjson = require("cjson.safe")

--[[
local rsa_algorithm =
{
	"md4","md5","ripemd160","sha1","sha224","sha256","sha384","sha512"
}
--]]


--rsa默认相关配置
local business_rsa =
{
    rsa_public_key = [[-----BEGIN RSA PUBLIC KEY-----
    MIIBCgKCAQEAuqWLDVg/r5KqldNgSBtW7SmQXESHhKOxHtLary5zawvu2KlnU0Nr
    +AVtXLjGTjqIXEUDBlGM+9gPhu5WrN5SJlSOPnk6kW35cRgVn4Rxl38us07Qe9qw
    eC5Vhi/moggfH/afd5Vdl2vH2ov1lmOHxQuA/buDNc+ndUKUQvlxXAqVRNlNfc5m
    n8umjlxInrQmJRVj/zVwZxDhr+JGy289SHhFc8duKEGNYHmQ+zMGrQiIVH6lTMrd
    ztmUCwNwWvauVvYQ7K9Xij548VUF7jmZszvSYppvC29jRs1SyCu50TnLFy+arR/9
    OkFoJZOhr38/qu1SEqb+Zqmag8uKZ9wRaQIDAQAB
    -----END RSA PUBLIC KEY-----
    ]],
    rsa_private_key = [[-----BEGIN RSA PRIVATE KEY-----
    MIIEowIBAAKCAQEAuqWLDVg/r5KqldNgSBtW7SmQXESHhKOxHtLary5zawvu2Kln
    U0Nr+AVtXLjGTjqIXEUDBlGM+9gPhu5WrN5SJlSOPnk6kW35cRgVn4Rxl38us07Q
    e9qweC5Vhi/moggfH/afd5Vdl2vH2ov1lmOHxQuA/buDNc+ndUKUQvlxXAqVRNlN
    fc5mn8umjlxInrQmJRVj/zVwZxDhr+JGy289SHhFc8duKEGNYHmQ+zMGrQiIVH6l
    TMrdztmUCwNwWvauVvYQ7K9Xij548VUF7jmZszvSYppvC29jRs1SyCu50TnLFy+a
    rR/9OkFoJZOhr38/qu1SEqb+Zqmag8uKZ9wRaQIDAQABAoIBACxVjB0EXERJE0n5
    ZoJaNCCrYcX45TPFahoHPbik0PeZYweF3awydJ/6Mgr3POtyDdfU8K38iv97R9zm
    GiJ/wIWoSg1e4GGQ/NI3RVOZsx2oMSCYVP9GZ+p0Hw57rE3KnhIKk8Bk81E3YcZw
    vkoVpDdSzzX152nNxFofEXaDJ8ETvpc1k8GSr9Fx+7Ee9lWSPaaia0ag+vaAw82x
    F+Cesa4z0FOqaV6s2VMXcsihGULTVYPWkDQsaIlMy3bhLRZ8VYoQsWAaJq/9OMWl
    kP1+ygf1Iq+tHCMkYe6rkNuBSNUBDqE+SdapeSHdZkMwst1KP7bruHmbFE1Qgexk
    K2Dfr20CgYEA3+B250Sg0J4vFd3HENmjDs8kqi6ry8LrN+J7AVJdKNc5x3Cn27ri
    fW8vjFlob5yweN6zJ9XRudPX9oLdm3BimpeLusTrTgPq0PI/Z/nripZi59MfTwtb
    6UZgJ/sdP6cSBCtyAIZ4MzliHg+vJAVVVPiMEAkmHWFKuz0+kwuN6FcCgYEA1W2G
    ah5MsYywylP0IZOfnd/pwS5ipGcsYl+/4mVxOdcQTkwYI2OMz/joLBDhK8LckacY
    iNDvGO8pEiYkJ6P02xaFXW1rFuRpDh9PqFSDFezTNzbDZ2702svcITIoiXyYoQKV
    imn1ubvTwmNEYYs6jyDEsdM9+2inB3PWud8wvD8CgYEA38jaUlbRgXd9jZgA8qD6
    U0VQWyUH6UhQI66qUinooXhycx/zSrtGxyerGdoNgPPZmxjRcNJVMDHIQMuThVsT
    1YAC1pEcvQFBadec9exmPEQTXbQ2KacrGsWUPKLRG91/LtfWvxurb1i+8VmwMot6
    PtOr/iOHC/tC3mNb91SnZ0UCgYB4ctla5kKuKRJU/VBX6rI4LPgFGCJ/WeLImfT2
    1f0ygVcoePVec34ymOyegeAyDETixoSoIhHt5nstTO02medEBc+6TFgVkU5gs/cG
    rrtUElWZYYShyRLSsB5Jdb8+6FxS8dxnQyl0arY1jEQ5MJQZ1oprOSZPzl4FbLCQ
    MY+VjQKBgGTcytW+1xKncEsPmt7uj+PvDeTOiVt9N42rJVdExH9nGa2rE3jFkJlg
    P6thUYGlhgTaAoHKsq9PztWbtYALh8PQMy7MMkKGFcHN0no9WVS29IUZb4Pr6gI9
    GFlmqa+UiFNP+YYDniIgcct/EXqInhqCswiInEifPzloHCrFhCLf
    -----END RSA PRIVATE KEY-----
    ]],
    rsa_password = "business_lihu_2018",
    rsa_pkcs8 = false,
    rsa_bits = 2048,
    algorithm = nil,
    rsa_key_type = ns_rsa.KEY_TYPE.PKCS1,
    rsa_padding =ns_rsa.PADDING.RSA_PKCS1_PADDING,
}


local _M = {
    _VERSION = "0.12.1"
}
local mt = {__index = _M}


function _M.create_key(_,bits,pkcs8)
	local rsa_public_key,rsa_private_key,err = ns_rsa:generate_rsa_keys(bits or business_rsa.rsa_bits,pkcs8 or business_rsa.rsa_pkcs8)
	if not rsa_public_key then
		log.day_list("business_common", "rsa","create_key generate_rsa_keys error="..err)
		return nil,nil
	end
	return rsa_public_key,rsa_private_key
end


--@param rsa_public_key
--@param rsa_private_key
--@param password rsa_private_key is encrypted, need password
--@param key_type 参考 ns_rsa.KEY_TYPE
--@param padding 参考 ns_rsa.PADDIN
--@param algorithm  参考 local rsa_algorithm = {} 签名算法
function _M.new(self, rsa_public_key, rsa_private_key, password, key_type, padding, algorithm)
    local param_list = {
        rsa_public_key = rsa_public_key or business_rsa.rsa_public_key,
        rsa_private_key = rsa_private_key or business_rsa.rsa_private_key,
        password = password or business_rsa.rsa_password,
        key_type = key_type or business_rsa.rsa_key_type,
        padding = padding or business_rsa.rsa_padding,
        algorithm = algorithm or business_rsa.algorithm
    }
    return setmetatable(param_list, mt)
end

--加密
function _M.encrypt(self, str)
    local param_list =
    {
        public_key = self.rsa_public_key,
        key_type = self.key_type,
        algorithm = self.algorithm,
        padding = self.padding,
        password = self.password
    }
    local pub, err = ns_rsa:new(param_list)
    if not pub then
        log.day_list("business_common", "rsa", "create public obj failed", err,uu.to_str(param_list))
        return nil, err
    end
    local encrypted, err = pub:encrypt(str)
    if not encrypted then
        log.day_list("business_common", "rsa", "encrypt failed", err)
        return nil, err
    end
    return encrypted
end

--解密
function _M.decrypt(self, str)
    local param_list = {
        private_key = self.rsa_private_key,
        key_type = self.key_type,
        algorithm = self.algorithm,
        padding = self.padding,
        password = self.password
    }
    local priv, err = ns_rsa:new(param_list)
    if not priv then
        log.day_list("business_common", "rsa", "create private obj failed", err,uu.to_str(param_list))
        return nil, err
    end
    local decrypted, err = priv:decrypt(str)
    if not decrypted then
        log.day_list("business_common", "rsa", "decrypt failed", err,uu.to_str(param_list))
        return nil, err
    end
    return decrypted
end

function _M.sign(self, str)
    local param_list =  {
        private_key = self.rsa_private_key,
        key_type = self.key_type,
        algorithm = self.algorithm,
        padding = self.padding,
        password = self.password
    }
    local priv, err = ns_rsa:new(param_list)
    if not priv then
        log.day_list("business_common", "rsa", "create private obj failed", err,uu.to_str(param_list))
        return nil, err
    end
    local sig, err = priv:sign(str)
    if not sig then
        log.day_list("business_common", "rsa", "private obj sign failed", err,uu.to_str(param_list))
        return nil, err
    end
    return sig
end

function _M.verify(self, str, sig)
    local param_list =        
    {
        public_key = self.rsa_public_key,
        key_type = self.key_type,
        algorithm = self.algorithm,
        padding = self.padding,
        password = self.password
    }
    local pub, err = ns_rsa:new(param_list)
    if not pub then
        log.day_list("business_common", "rsa", "create public obj failed", err,uu.to_str(param_list))
        return false, err
    end
    local verify, err = pub:verify(str, sig)
    if not verify then
        log.day_list("business_common", "rsa", "private public obj verify failed", err,uu.to_str(param_list))
        return false, err
    end
    return verify
end

return _M


